import numpy as np
import matplotlib.pyplot as plt

# 中文和负号正常显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

def find_inflection_points(f, x_range):
    """
    找到函数的拐点
    """
    x = np.linspace(x_range[0], x_range[1], 10000)
    y = f(x)
    
    # 计算一阶和二阶导数
    dy = np.gradient(y, x)
    d2y = np.gradient(dy, x)
    
    # 寻找拐点（二阶导数变号的点）
    inflection_points = []
    for i in range(1, len(d2y)-1):
        if (d2y[i] > 0 and d2y[i+1] < 0) or (d2y[i] < 0 and d2y[i+1] > 0):
            inflection_points.append((x[i], y[i]))
        elif abs(d2y[i]) < 1e-5 and (d2y[i-1] * d2y[i+1] < 0):
            inflection_points.append((x[i], y[i]))
    
    return x, y, dy, d2y, inflection_points

# 定义函数
def f(x):
    return x**3 - 4*x + 4

x, y, dy, d2y, inflection_points = find_inflection_points(f, [-3, 3])

# 绘制结果
plt.figure(figsize=(12, 8))

# 绘制函数图像和拐点
plt.subplot(2, 1, 1)
plt.plot(x, y, 'b-', linewidth=2, label='y = x^3 - 4x + 4')
if inflection_points:
    for point in inflection_points:
        plt.plot(point[0], point[1], 'ro', markersize=10, label='拐点')
plt.xlabel('x')
plt.ylabel('y')
plt.title('函数图像及拐点')
plt.legend()
plt.grid(True, alpha=0.3)

# 绘制二阶导数
plt.subplot(2, 1, 2)
plt.plot(x, d2y, 'g-', linewidth=2, label="y'' = 6x")
plt.axhline(y=0, color='k', linestyle='-', alpha=0.3)
plt.xlabel('x')
plt.ylabel("y''")
plt.title('二阶导数')
plt.legend()
plt.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

print("找到的拐点：")
for point in inflection_points:
    print(f"({point[0]:.2f}, {point[1]:.2f})")